import express from "express";
import path from "path";
import fs from "fs";
import compressing from "compressing"; //zip插件
import formidable from "formidable"; //表单插件
let router = express.Router();

export let rootPath = "./ax-apps"; //应用静态资源根目录
export let tempPathUpload = `./ax-apps-temp/upload`; //应用静态资源文件上传缓存目录
export let tempPathDownload = `./ax-apps-temp/download-zip`; //应用静态资源文件下载缓存目录(zip压缩下载)

router.use(function (req, res, next) {
  let params = {};

  switch (req.method) {
    case "GET":
      params = req.query || {};
      break;
    case "POST":
      params = req.body || {};
      break;
    default:
      break;
  }

  if (req.url != "/upload" && !params.appId) {
    return res.json({ code: -1, message: "缺少参数:appId(应用id)" });
  }
  if (req.url != "/upload" && typeof params.appId != "string") {
    return res.json({ code: -1, message: "参数appId的数据类型必须为字符串" });
  }
  // if (!params.appId) {
  //   return res.json({ code: -1, message: "缺少参数:appId(应用id);参数类型:字符串" });
  // }
  next();
});
//下载资源
router.get("/download/", function (req, res, next) {
  console.log("下载资源", req.query);
  let params = req.query;
  let pathArr = (params.fullPath ? [rootPath, params.fullPath] : [rootPath, params.appId, params.path]).filter((i) => i);
  let filePath = path.join(...pathArr);
  console.log("下载资源路径", filePath);
  if (!fs.existsSync(filePath)) {
    return res.json({ code: -1, message: "没有资源: " + filePath });
  }
  if (fs.statSync(filePath).isFile()) {
    return res.download(filePath);
  }

  let pathParser = path.parse(filePath);
  delete pathParser.base;
  pathParser.dir = tempPathDownload;
  pathParser.ext = "." + Date.now() + Math.random() + ".zip";
  if (!fs.existsSync(pathParser.dir)) {
    fs.mkdirSync(pathParser.dir, { recursive: true });
  }
  let zipFileName = `${pathParser.name}.zip`;
  let zipFilePath = path.format(pathParser);
  let zipStream = fs.createWriteStream(zipFilePath);
  let streamDir = new compressing.zip.Stream();

  function handleError(error) {
    console.error("[资源打包异常]", error);
    res.json({ code: -1, message: "资源下载失败", error });
  }
  function handleFinish() {
    // console.log("[资源打包完成]", zipFileName, path.resolve(zipFilePath));
    // res.json({ zipFilePath });
    res.download(zipFilePath, zipFileName, (error) => {
      // console.log("[发送资源结束]");
      error && console.error("[发送资源 error]", error);
      fs.existsSync(zipFilePath) && fs.rmSync(zipFilePath); //下载结束,清楚缓存文件
    });
  }
  streamDir.addEntry(filePath, { ignoreBase: true }); //将文件夹打包成zip文件
  streamDir.on("error", handleError).pipe(zipStream).on("error", handleError).on("finish", handleFinish);
});

//上传文件
router.post("/upload/", async function (req, res, next) {
  let uploadDir = tempPathUpload;
  !fs.existsSync(uploadDir) && fs.mkdirSync(uploadDir, { recursive: true }); // 判断文件夹是否存在,没用递归创建文件夹
  let form = formidable({
    // encoding: "utf-8", // 设置编码
    uploadDir: uploadDir, // 设置上传目录
    keepExtensions: true, // 保留后缀
    maxFileSize: 100 * 1024 * 1024, // 最大文件大小 （默认20M => 2 * 1024 * 1024 ）
    minFileSize: 0, //最小文件大小
    maxTotalFileSize: 100 * 1024 * 1024,
    maxFiles: 100, //最大文件数
    allowEmptyFiles: true
  });
  try {
    const [fields, filesForm] = await form.parse(req);
    const params = {
      appId: (fields.appId || [])[0],
      folderPath: (fields.folderPath || [])[0],
      replace: (fields.replace || [])[0]
    };
    const files = (filesForm || {}).files;
    // console.warn("[解析表单结束][准备保存文件]", params, fields, files);
    let filesPath = [];
    for (const i in files) {
      let file = files[i];
      let originalFilename = file.originalFilename;
      let filePath = path.join(...[rootPath, params.appId, params.folderPath, originalFilename].filter((i) => i)); //后端文件路径存储路径(相对路径)

      //同名文件上传策略;默认不覆盖
      if (!params.replace && fs.existsSync(filePath)) {
        let pathParse = path.parse(filePath);
        delete pathParse.base;
        pathParse.name = pathParse.name + `_${Date.now()}`; //TODO 新路径依然可能重复
        filePath = path.format(pathParse);
      }

      const folderPath = path.dirname(filePath); // 获取文件所在的文件夹路径
      !fs.existsSync(folderPath) && fs.mkdirSync(folderPath, { recursive: true }); // 判断文件夹是否存在,没用递归创建文件夹
      fs.existsSync(file.filepath) && fs.renameSync(file.filepath, filePath); //将插件缓存的文件移动到相应目录

      let filePathPrefix = path.join(...[rootPath, params.appId].filter((i) => i));
      let assetsPath = filePath.substring(filePathPrefix.length + 1).replaceAll("\\", "/"); //生成前端资源访问路径(相对路径)
      console.log("[保存文件]", assetsPath, filePath);
      filesPath.push(assetsPath);
    }
    // console.log("[文件上传成功]", filesPath);
    res.json({ code: 200, message: "文件上传成功", data: filesPath });
  } catch (error) {
    console.error("[文件上传异常]", error);
    res.json({ code: -1, message: "文件上传异常", error: error.message });
  }

  // console.debug(e);
});
//添加文件夹
router.post("/addFolder/", function (req, res, next) {
  try {
    let params = req.body || {};
    let folder = "新建文件夹-" + Date.now();
    let pathArr = [rootPath, params.appId, params.folderPath, folder].filter((i) => i);
    let folderPath = path.join(...pathArr); //资源目录真实路径
    !fs.existsSync(folderPath) && fs.mkdirSync(folderPath, { recursive: true }); // 判断文件夹是否存在,没用递归创建文件夹
    res.json({ code: 200, message: "文件夹添加成功", data: folder });
  } catch (error) {
    console.error("[文件夹添加异常]", error);
    res.json({ code: -1, message: "文件夹添加异常", error: error.message });
  }
});
//资源复制
router.post("/copy", async function (req, res, next) {
  try {
    let params = req.body || {};
    let pathArr = (params.fullPath ? [rootPath, params.fullPath] : [rootPath, params.appId, params.path]).filter((i) => i);
    let sourcePath = path.join(...pathArr);

    if (!fs.existsSync(sourcePath)) {
      return res.json({ code: -1, message: "资源不存在" });
    }

    let pathParse = path.parse(sourcePath);
    delete pathParse.base;
    let pathArrTarget = [rootPath, params.appId, params.folderPath].filter((i) => i);
    pathParse.dir = path.join(...pathArrTarget);
    let targetPath = path.format(pathParse);
    if (fs.existsSync(targetPath)) {
      pathParse.name = pathParse.name + `-copy${Date.now()}`; //TODO 新路径依然可能重复
      targetPath = path.format(pathParse);
    }

    if (fs.existsSync(targetPath)) {
      return res.json({ code: -1, message: "复制失败;已存在目标资源:" + name });
    }

    console.debug("[准备资源复制]", sourcePath, " -> ", targetPath);
    await fs.cpSync(sourcePath, targetPath, { recursive: true }); //复制文件或目录
    res.json({ code: 200, message: "资源复制成功", data: pathParse.name });
  } catch (error) {
    console.error("[资源复制异常]", error);
    res.json({ code: -1, message: "资源复制异常", error: error.message });
  }
});
//资源重命名
router.post("/rename", async function (req, res, next) {
  try {
    let params = req.body || {};
    if (!params.name) {
      return res.json({ code: -1, message: "没有新的资源名称" });
    }

    let pathArr = [rootPath, params.appId, params.path].filter((i) => i);
    let sourcePath = path.join(...pathArr);
    if (!fs.existsSync(sourcePath)) {
      return res.json({ code: -1, message: "资源不存在" });
    }

    let pathParse = path.parse(sourcePath);
    delete pathParse.base;
    let pathParseNew = path.parse(params.name);
    pathParse.name = pathParseNew.ext == pathParse.ext ? pathParseNew.name : params.name;
    let targetPath = path.format(pathParse);

    if (fs.existsSync(targetPath)) {
      return res.json({ code: -1, message: "资源重命名失败;资源名称已存在: " + params.name });
    }
    await fs.renameSync(sourcePath, targetPath); //
    res.json({ code: 200, message: "资源重命名成功", data: targetPath.replaceAll("\\", "/") });
  } catch (error) {
    console.error("[资源重命名异常]", error);
    res.json({ code: -1, message: "资源重命名异常", error: error.message });
  }
});
//查询目录下的文件列表
router.get("/getList/", function (req, res, next) {
  try {
    let query = req.query || {};
    let appId = query.appId || "";
    let folder = path.join(rootPath, appId, query.folderPath); //资源目录真实路径

    console.log("[查询目录下的资源列表]", folder, req.url, query);
    let files = fs.existsSync(folder) ? fs.readdirSync(folder) : [];
    // console.log(files);
    let fileList = [];
    files.forEach((item, i) => {
      let assetPath = path.join(query.folderPath, item).replaceAll("\\", "/"); //生成前端页面使用的资源访问路径(相对路径)
      // let filePath = path.join(query.folderPath, item).replaceAll("\\", "/"); //生成资源后端访问路径(相对路径)
      let statPath = path.join(folder, item);
      // console.log(filePath);
      if (fs.existsSync(statPath)) {
        let stat = fs.statSync(statPath);
        fileList.push({
          name: item,
          path: assetPath,
          // filePath: filePath,
          size: stat.size,
          time: stat.birthtime,
          birthtime: stat.birthtime,
          ctime: stat.ctime,
          type: stat.isDirectory() ? "dir" : item
        });
      }
    });

    // console.log("[资源列表]", fileList);
    res.json({
      code: fileList.length ? 200 : -1,
      message: fileList.length ? "目录解析成功" : "当前目录没有文件",
      data: fileList
    });
  } catch (error) {
    console.error("[资源列表查询异常]", error);
    res.json({ code: -1, message: "目录解析异常", error });
  }
});

//资源复制
router.post("/copy", function (req, res, next) {
  console.debug(["准备复制资源"], req.body);
  let params = req.body || {};
  let files = params.files;
  let result = { code: -1, message: "没有需要复制的资源列表" };

  if (!files || !files.length) {
    return res.json(result);
  }
  let appId = params.appId || "";

  try {
    for (const i in files) {
      let pathItem = files[i];
      let dir = [appId, pathItem].filter((item) => item && item != "/").join("/"); //资源相对路径
      let filePath = `${rootPath}${dir}`; //资源真实路径
      console.debug(["复制资源][filePath"], filePath);
      if (!fs.existsSync(filePath)) {
        continue;
      }
      fs.statSync(filePath).isDirectory() ? fs.rmdirSync(filePath, { recursive: true }) : fs.rmSync(filePath); //资源存在才需要删除; //目标目录存在,删除目标目录
    }
    result.code = 200;
    result.message = "删除成功";
  } catch (error) {
    console.debug(["文件删除异常"], error);
    result.message = "文件删除失败";
    result.error = error;
  }
  res.json(result);
});

//删除资源
router.post("/remove", function (req, res, next) {
  console.debug(["准备删除资源"], req.body);
  let params = req.body || {};
  let files = params.files;
  let result = { code: -1, message: "没有需要删除的资源列表" };
  if (!files || !files.length) {
    return res.json(result);
  }

  let appId = params.appId || "";
  try {
    for (const i in files) {
      let pathArr = [rootPath, appId, files[i]].filter((item) => item);
      let filePath = path.join(...pathArr); //资源真实路径
      console.debug(["准备删除资源filePath"], filePath);
      if (!fs.existsSync(filePath)) {
        continue;
      }
      fs.statSync(filePath).isDirectory() ? fs.rmdirSync(filePath, { recursive: true }) : fs.rmSync(filePath); //资源存在才需要删除; //目标目录存在,删除目标目录
    }
    result.code = 200;
    result.message = "删除成功";
  } catch (error) {
    console.debug(["文件删除异常"], error);
    result.message = "文件删除失败";
    result.error = error;
  }
  res.json(result);
});

export default router;
